package com.governtalk.backend.service.impl;

import com.governtalk.backend.dto.forum.CategoryDto;
import com.governtalk.backend.dto.forum.PostDto;
import com.governtalk.backend.dto.forum.CommentDto;
import com.governtalk.backend.entity.Category;
import com.governtalk.backend.entity.Post;
import com.governtalk.backend.entity.Comment;
import com.governtalk.backend.entity.User;
import com.governtalk.backend.repository.CategoryRepository;
import com.governtalk.backend.repository.PostRepository;
import com.governtalk.backend.repository.CommentRepository;
import com.governtalk.backend.service.ForumService;
import com.governtalk.backend.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ForumServiceImpl implements ForumService {
    
    @Autowired
    private CategoryRepository categoryRepository;
    
    @Autowired
    private PostRepository postRepository;
    
    @Autowired
    private CommentRepository commentRepository;
    
    @Autowired
    private UserService userService;
    
    @Override
    public List<CategoryDto> getCategories() {
        List<Category> categories = categoryRepository.findByParentIdIsNullAndIsActiveTrueOrderBySortOrder();
        return categories.stream().map(this::convertCategoryToDto).collect(Collectors.toList());
    }
    
    @Override
    public Page<PostDto> getPosts(Long categoryId, String keyword, String sortBy, String status, Pageable pageable) {
        Page<Post> posts;
        
        if (keyword != null && !keyword.isEmpty()) {
            posts = postRepository.findByKeywordAndStatus(keyword, pageable);
        } else if (categoryId != null) {
            posts = postRepository.findByCategoryIdAndStatus(categoryId, Post.PostStatus.APPROVED, pageable);
        } else {
            posts = postRepository.findByStatus(Post.PostStatus.APPROVED, pageable);
        }
        
        return posts.map(this::convertPostToDto);
    }
    
    @Override
    public List<PostDto> getHotPosts(int count) {
        Pageable pageable = PageRequest.of(0, count);
        List<Post> posts = postRepository.findHotPosts(pageable);
        return posts.stream().map(this::convertPostToDto).collect(Collectors.toList());
    }
    
    @Override
    public List<PostDto> getLatestPosts(int count) {
        Pageable pageable = PageRequest.of(0, count);
        List<Post> posts = postRepository.findLatestPosts(pageable);
        return posts.stream().map(this::convertPostToDto).collect(Collectors.toList());
    }
    
    @Override
    public PostDto getPostDetail(Long postId) {
        Post post = postRepository.findByIdWithUser(postId)
                .orElseThrow(() -> new RuntimeException("Post not found"));
        
        // 增加浏览次数
        post.setViewCount(post.getViewCount() + 1);
        postRepository.save(post);
        
        return convertPostToDto(post);
    }
    
    @Override
    public PostDto createPost(PostDto postDto) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userService.findByUsername(username);
        
        Post post = Post.builder()
                .title(postDto.getTitle())
                .content(postDto.getContent())
                .user(user)
                .categoryId(postDto.getCategoryId())
                .viewCount(0)
                .likeCount(0)
                .commentCount(0)
                .shareCount(0)
                .status(Post.PostStatus.APPROVED)
                .isPinned(false)
                .isHot(false)
                .build();
        
        Post savedPost = postRepository.save(post);
        return convertPostToDto(savedPost);
    }
    
    @Override
    public PostDto updatePost(Long postId, PostDto postDto) {
        Post post = postRepository.findById(postId)
                .orElseThrow(() -> new RuntimeException("Post not found"));
        
        post.setTitle(postDto.getTitle());
        post.setContent(postDto.getContent());
        post.setCategoryId(postDto.getCategoryId());
        post.setUpdatedAt(LocalDateTime.now());
        
        Post savedPost = postRepository.save(post);
        return convertPostToDto(savedPost);
    }
    
    @Override
    public void deletePost(Long postId) {
        postRepository.deleteById(postId);
    }
    
    @Override
    public Map<String, Object> likePost(Long postId) {
        Post post = postRepository.findById(postId)
                .orElseThrow(() -> new RuntimeException("Post not found"));
        
        post.setLikeCount(post.getLikeCount() + 1);
        postRepository.save(post);
        
        Map<String, Object> result = new HashMap<>();
        result.put("likeCount", post.getLikeCount());
        result.put("isLiked", true);
        return result;
    }
    
    @Override
    public Page<CommentDto> getPostComments(Long postId, Long parentId, Pageable pageable) {
        Page<Comment> comments;
        
        if (parentId != null) {
            comments = commentRepository.findByParentIdAndStatus(parentId, Comment.CommentStatus.APPROVED, pageable);
        } else {
            comments = commentRepository.findByPostIdAndStatus(postId, Comment.CommentStatus.APPROVED, pageable);
        }
        
        return comments.map(this::convertCommentToDto);
    }
    
    @Override
    public CommentDto createComment(CommentDto commentDto) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userService.findByUsername(username);
        
        Post post = postRepository.findById(commentDto.getPostId())
                .orElseThrow(() -> new RuntimeException("Post not found"));
        
        Comment comment = Comment.builder()
                .content(commentDto.getContent())
                .user(user)
                .post(post)
                .parentId(commentDto.getParentId())
                .likeCount(0)
                .status(Comment.CommentStatus.APPROVED)
                .build();
        
        Comment savedComment = commentRepository.save(comment);
        
        // 更新帖子的评论数
        post.setCommentCount(post.getCommentCount() + 1);
        postRepository.save(post);
        
        return convertCommentToDto(savedComment);
    }
    
    @Override
    public void deleteComment(Long commentId) {
        commentRepository.deleteById(commentId);
    }
    
    @Override
    public Map<String, Object> likeComment(Long commentId) {
        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new RuntimeException("Comment not found"));
        
        comment.setLikeCount(comment.getLikeCount() + 1);
        commentRepository.save(comment);
        
        Map<String, Object> result = new HashMap<>();
        result.put("likeCount", comment.getLikeCount());
        result.put("isLiked", true);
        return result;
    }
    
    @Override
    public void approvePost(Long postId, String status) {
        Post post = postRepository.findById(postId)
                .orElseThrow(() -> new RuntimeException("Post not found"));
        
        post.setStatus(Post.PostStatus.valueOf(status));
        post.setUpdatedAt(LocalDateTime.now());
        postRepository.save(post);
    }
    
    @Override
    public Page<PostDto> getPendingPosts(Pageable pageable) {
        Page<Post> posts = postRepository.findPendingPosts(pageable);
        return posts.map(this::convertPostToDto);
    }
    
    private CategoryDto convertCategoryToDto(Category category) {
        return CategoryDto.builder()
                .id(category.getId())
                .name(category.getName())
                .description(category.getDescription())
                .createdAt(category.getCreatedAt())
                .updatedAt(category.getUpdatedAt())
                .build();
    }
    
    private PostDto convertPostToDto(Post post) {
        return PostDto.builder()
                .id(post.getId())
                .title(post.getTitle())
                .content(post.getContent())
                .categoryId(post.getCategoryId())
                .userId(post.getUser() != null ? post.getUser().getId() : null)
                .username(post.getUser() != null ? post.getUser().getUsername() : "匿名用户")
                .avatar(post.getUser() != null ? post.getUser().getAvatarUrl() : null)
                .viewCount(post.getViewCount())
                .likeCount(post.getLikeCount())
                .commentCount(post.getCommentCount())
                .shareCount(post.getShareCount())
                .status(post.getStatus().name())
                .isTop(post.getIsPinned())
                .isHot(post.getIsHot())
                .createdAt(post.getCreatedAt())
                .updatedAt(post.getUpdatedAt())
                .build();
    }
    
    private CommentDto convertCommentToDto(Comment comment) {
        return CommentDto.builder()
                .id(comment.getId())
                .postId(comment.getPost().getId())
                .content(comment.getContent())
                .userId(comment.getUser().getId())
                .username(comment.getUser().getUsername())
                .avatar(comment.getUser().getAvatarUrl())
                .parentId(comment.getParentId())
                .likeCount(comment.getLikeCount())
                .createdAt(comment.getCreatedAt())
                .updatedAt(comment.getUpdatedAt())
                .build();
    }
}
